home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************************
-
- Gnucleus - A node application for the Gnutella network
- Copyright (C) 2000 John Marshall
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- For support, questions, comments, etc...
- E-Mail:
- swabby@c0re.net
-
- Address:
- 21 Cadogan Way
- Nashua, NH, USA 03062
-
- ********************************************************************************/
-
- // GnuHash.cpp: implementation of the CGnuHash class.
- //
- //////////////////////////////////////////////////////////////////////
-
- #include "stdafx.h"
- #include "Gnucleus.h"
- #include "GnucleusDoc.h"
-
- #include "ViewSearch.h"
-
- #include "GnuTransfer.h"
- #include "GnuSock.h"
- #include "GnuHash.h"
- #include "GnuControl.h"
-
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
- CGnuHash::CGnuHash()
- {
- GnuComm = NULL;
- HashEntries = 0;
- Current = 0;
- Old = 1;
-
- for(int i = 0; i < HASH_SIZE; i++)
- {
- Table[0][i] = NULL;
- Table[1][i] = NULL;
- }
- }
-
- CGnuHash::CGnuHash(CGnuControl *pGnuComm)
- {
- GnuComm = pGnuComm;
- HashEntries = 0;
- Current = 0;
- Old = 1;
-
- for(int i = 0; i < HASH_SIZE; i++)
- {
- Table[0][i] = NULL;
- Table[1][i] = NULL;
- }
- }
-
- CGnuHash::~CGnuHash()
- {
- for(int i = 0; i < HASH_SIZE; i++)
- {
- if(Table[0][i] != NULL)
- delete Table[0][i];
-
- if(Table[1][i] != NULL)
- delete Table[1][i];
- }
- }
-
- void CGnuHash::Insert(GUID *Guid, CGnuSock *Origin)
- {
- DWORD key = CreateKey(Guid);
- int attempts = MAX_REHASH;
-
- while(Table[Current][key] != NULL && attempts--)
- key = (key + REHASH_VALUE) % HASH_SIZE;
-
- // Check to see if table is full
- if(Table[Current][key] != NULL)
- {
- // time to clean out the old and switch
- ClearTable(Old);
- if (Current == 0)
- {
- Current = 1;
- Old = 0;
- }
- else
- {
- Current = 0;
- Old = 1;
- }
- key = CreateKey(Guid); // don't need to rehash, we know it's empty
- }
-
- Table[Current][key] = new key_data;
- Table[Current][key]->Guid = *Guid;
- Table[Current][key]->Origin = Origin;
- HashEntries++;
- }
-
- key_data* CGnuHash::FindValue(GUID *Guid)
- {
- DWORD key = CreateKey(Guid);
- int attempts = MAX_REHASH; // HASH_SIZE, I dont want to search forever
-
- // search the current table
- while(attempts--)
- {
- if(Table[Current][key] != NULL && CompareGuid(&Table[Current][key]->Guid, Guid))
- return Table[Current][key];
-
- key = (key + REHASH_VALUE) % HASH_SIZE;
- }
-
- // try the old table
- attempts = MAX_REHASH;
- while(attempts--)
- {
- if(Table[Old][key] != NULL && CompareGuid(&Table[Old][key]->Guid, Guid))
- return Table[Old][key];
-
- key = (key + REHASH_VALUE) % HASH_SIZE;
- }
-
- // not found ...
- return NULL;
- }
-
- bool CGnuHash::CheckEmpty(int which)
- {
- for(int i = 0; i < HASH_SIZE; i++)
- if(Table[which][i] != NULL)
- return 0;
-
- return 1;
- }
-
- DWORD CGnuHash::CreateKey(GUID *Guid)
- {
- byte *GuidRaw = (byte *) Guid;
-
- // XOR every 4 bytes together ...
- DWORD key = (GuidRaw[0] ^ GuidRaw[4] ^ GuidRaw[8] ^ GuidRaw[12]) +
- 256 * (GuidRaw[1] ^ GuidRaw[5] ^ GuidRaw[9] ^ GuidRaw[13]) +
- 256 * 256 * (GuidRaw[2] ^ GuidRaw[6] ^ GuidRaw[10] ^ GuidRaw[14]) +
- 256 * 256 * 256 * (GuidRaw[3] ^ GuidRaw[7] ^ GuidRaw[11] ^ GuidRaw[15]);
-
- // and modulo it down to size
- key %= HASH_SIZE;
-
- return key;
- }
-
- bool CGnuHash::CompareGuid(GUID *Guid1, GUID *Guid2)
- {
- byte *GuidRaw1 = (byte *) Guid1;
- byte *GuidRaw2 = (byte *) Guid2;
-
- for(int i = 0; i < 16; i++)
- if(GuidRaw1[i] != GuidRaw2[i])
- return 0;
-
- return 1;
- }
-
- void CGnuHash::ClearTable(int which)
- {
- for(int i = 0; i < HASH_SIZE; i++)
- if(Table[which][i] != NULL)
- {
- delete Table[which][i];
- Table[which][i] = NULL;
- }
-
- HashEntries = 0;
- }